#include <math.h>
#include <QDebug>
#include <QFontMetrics>
#include <QPainter>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->cursor_x = 0;
    this->cursor_y = 0;
    this->cursor_show = false;

    this->timer.setInterval(1000);
    this->connect(&this->timer, SIGNAL(timeout()), this, SLOT(cursorTimeout()));
    this->timer.start();

    QList<QString> empty;
    this->lines.append(empty);
    this->text_line = 0;
    this->text_column = 0;
    this->is_mouse_down = false;
    this->is_ctrl = false;

    this->cb = QApplication::clipboard();
}

MainWindow::~MainWindow()
{
    this->timer.stop();
    delete ui;
}

void MainWindow::cursorTimeout(QPrivateSignal) {
    this->cursor_show = !this->cursor_show;
    this->update();
}

void MainWindow::paintEvent(QPaintEvent *) {
    // 初始化绘图环境
    QPainter p(this);

    // 绘制背景
    p.setPen(QColor(255, 255, 255));
    p.setBrush(QBrush(QColor(255, 255, 255)));
    p.drawRect(0, 0, this->width(), this->height());

    // 绘制文本
    p.setFont(QFont("宋体", 50));
    QFontMetrics fm(p.font());
    p.setPen(QColor(0, 0, 0));
    int start_line_x = 0;
    int start_line_y = 0;
    int start_line_width = 0;
    int start_line_width_x = 0;
    int end_line_x = 0;
    int end_line_y = 0;
    int line_width;
    int fm_height = fm.height();
    int line_height = fm_height;
    QString before_text, sel_text = "";
    bool after_sel = false;
    for (QList<QString> str_list : this->lines) {
        line_width = 0;
        for (QString str : str_list) {
            // 选中文本
            if ((this->start_sel_text_x != this->end_sel_text_x ||
                    this->start_sel_text_y != this->end_sel_text_y) &&
                    this->start_sel_text_x == start_line_x &&
                    this->start_sel_text_y == start_line_y &&
                    this->end_sel_text_x == end_line_x &&
                    this->end_sel_text_y == end_line_y) {
                // 背景色
                p.setPen(QColor(0, 120, 215));
                p.setBrush(QColor(0, 120, 215));
                p.drawRect(start_line_width_x, line_height - fm_height, start_line_width, fm_height);
                p.setPen(QColor(255, 255, 255));
                p.drawText(start_line_width_x, line_height, sel_text);
                this->selected_text = sel_text + str;
                after_sel = true;
            } else {
                p.setPen(QColor(0, 0, 0));
                p.drawText(line_width, line_height, str);
                after_sel = false;
            }
            if (after_sel) {
                p.setPen(QColor(0, 0, 0));
                p.drawText(start_line_width_x + fm.width(sel_text), line_height, str);
            }
            if (this->start_sel_text_x == start_line_x && end_line_x == 0) {
                end_line_x = start_line_x;
            }
            if (this->start_sel_text_x == start_line_x &&
                    this->end_sel_text_x > end_line_x) {
                start_line_width += fm.width(str);
                ++end_line_x;
                if (this->end_sel_text_x == end_line_x) {
                    p.setPen(QColor(0, 120, 215));
                    p.setBrush(QColor(0, 120, 215));
                    p.drawRect(start_line_width_x, line_height - fm_height, start_line_width, fm_height);
                    p.setPen(QColor(255, 255, 255));
                    p.drawText(start_line_width_x, line_height, sel_text + str);
                }
                sel_text += str;
            } else if (this->start_sel_text_x > start_line_x) {
                start_line_width_x += fm.width(str);
                ++start_line_x;
            } else {
                ++start_line_x;
                ++end_line_x;
            }
            line_width += fm.width(str);
            before_text = str;
        }
        line_height += fm_height;
        if (this->start_sel_text_y == start_line_y) {
            ++end_line_y;
        } else {
            ++start_line_y;
        }
    }

    // 绘制光标
    if (this->cursor_show) {
        p.setPen(QColor(0, 0, 0));
    } else {
        p.setPen(QColor(255, 255, 255));
    }
    int x1, y1, y2;
    if (this->cursor_x >= 0) {
        x1 = 0;
        int i = 0;
        for (QString str : this->lines.at(this->cursor_y)) {
            if (i >= this->cursor_x) {
                break;
            }
            x1 += fm.width(str);
            ++i;
        }
    } else {
        x1 = -1;
    }
    if (this->cursor_y >= 0) {
        y1 = this->cursor_y * fm_height;
        y2 = (this->cursor_y + 1) * fm_height;
    } else {
        y1 = -1;
    }
    if (x1 > -1 && y1 > -1) {
        p.drawLine(x1, y1, x1, y2);
    }
}

void MainWindow::keyPressEvent(QKeyEvent *event) {
    int k = event->key();
    QString text = event->text();
    if (text == "") {
        switch (k) {
        case Qt::Key_Up:
        {
            --this->cursor_y;
        }
            break;
        case Qt::Key_Down:
        {
            ++this->cursor_y;
        }
            break;
        case Qt::Key_Left:
        {
            --this->cursor_x;
        }
            break;
        case Qt::Key_Right:
        {
            ++this->cursor_x;
        }
            break;
        case Qt::Key_Control:
        {
            this->is_ctrl = true;
        }
            break;
        default:
            break;
        }
    } else {
        switch (k) {
        case Qt::Key_Return:
        case Qt::Key_Enter:
        {
            QList<QString> empty;
            this->lines.append(empty);
            this->cursor_x = 0;
            ++this->cursor_y;
        }
            break;
        case Qt::Key_Backspace:
        {
            this->lines[this->cursor_y].removeAt(this->cursor_x - 1);
            --this->cursor_x;
        }
            break;
        case Qt::Key_Delete:
        {
            this->lines[this->cursor_y].removeAt(this->cursor_x);
        }
            break;
        default:
        {
            if (this->is_ctrl) {
                switch (k) {
                case Qt::Key_C:
                {
                    this->cb->setText(this->selected_text);
                }
                    break;
                case Qt::Key_V:
                {
                    this->lines[this->cursor_y].insert(this->cursor_x, this->selected_text);
                    this->cursor_x += this->selected_text.length();
                }
                    break;
                default:
                    break;
                }
            } else {
                this->lines[this->cursor_y].insert(this->cursor_x, text);
                ++this->cursor_x;
            }
        }
            break;
        }
    }
    this->update();
}

void MainWindow::keyReleaseEvent(QKeyEvent *event) {
    switch (event->key()) {
    case Qt::Key_Control:
    {
        this->is_ctrl = false;
    }
        break;
    default:
        break;
    }
}

void MainWindow::mousePressEvent(QMouseEvent *event) {
    Qt::MouseButton b = event->button();
    QPoint p = event->pos();
    int x = p.x();
    int y = p.y();
    QFontMetrics fm(QFont("宋体", 50));

    switch (b) {
    case Qt::LeftButton:
    {
        this->selected_text = "";
        this->is_mouse_down = true;
        int w = 0;
        int before_w = 0;
        int column = 0;
        this->cursor_y = (int)round(y / fm.height());
        if (this->cursor_y >= this->lines.length()) {
            this->cursor_y = this->lines.length() - 1;
        }
        for (QString str : this->lines.at(this->cursor_y)) {
            w += fm.width(str);
            int res = x - w;
            int before_res = x - before_w;
            if (res < 0) {
                if (abs(before_res) < abs(res)) {
                    break;
                }
            }
            before_w = w;
            ++column;
        }
        this->cursor_x = column;
        this->start_sel_text_y = this->cursor_y;
        this->start_sel_text_x = this->cursor_x;
        this->end_sel_text_x = this->start_sel_text_x;
        this->end_sel_text_y = this->start_sel_text_y;
    }
        break;
    default:
        break;
    }
    this->update();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event) {
    Qt::MouseButton b = event->button();
    switch (b) {
    case Qt::LeftButton:
    {
        this->is_mouse_down = false;
    }
        break;
    default:
        break;
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event) {
    QPoint p = event->pos();
    int x = p.x();
    int y = p.y();
    QFontMetrics fm(QFont("宋体", 50));
    if (this->is_mouse_down) {
        int w = 0;
        int before_w = 0;
        int _x = 0;
        this->cursor_y = (int)round(y / fm.height());
        if (this->cursor_y >= this->lines.length()) {
            this->cursor_y = this->lines.length() - 1;
        }
        for (QString str : this->lines.at(this->cursor_y)) {
            w += fm.width(str);
            int res = x - w;
            int before_res = x - before_w;
            if (res < 0) {
                if (abs(before_res) < abs(res)) {
                    break;
                }
            }
            before_w = w;
            ++_x;
        }
        this->cursor_x = _x;
        this->end_sel_text_y = this->cursor_y;
        this->end_sel_text_x = this->cursor_x;
    }
    this->update();
}
